hsweb的系列学习——hsweb-easy-orm分析 上

hsweb的系列学习——hsweb-easy-orm分析 上

对于此orm框架的封装,首先要看的便是:hsweb-easy-orm-core

整体思路:因为是为动态表单设计的orm框架,所以要有为映射包装的PO类和反映到表元素的元数据类MetaData,

以及对这些bean进行操作的各种周边(最多的也就是curd的细节分拆)

一,映射包装的PO类

列的设定

我们的curd操作的基本元素首先是表,而我们操作的铁定就是po类,表中的基本元素首先是列,列包含两个属性,名字和字段类型

那么对于这个orm框架中的体现就是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package org.hsweb.ezorm.core.param;

/**
* @author zhouhao
* @since 1.1
*/
public class Column {
private String name;

private String type;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public Column type(String type) {
this.type = type;
return this;
}

public static Column build(String name) {
Column column = new Column();
column.setName(name);
return column;
}
}

此处单独定义了ColumnType,暂时未见使用

1
2
3
4
5
6
7
8
9
10
package org.hsweb.ezorm.core.param;

/**
* @author zhouhao
* @since 1.1
*/
public interface ColumnType {
String def = "";

}

SQL的参数设定

对列的一系列的操作其实是操作字段及所涉及的数据,那么我们所要设定的地方有:

通过参考一个sql语句可以知道,操作一个字段往往会涉及到where后面的条件,以及要处理的字段如in{...}不处理的字段 not in{...} 具体代码里面的体现就是:

首先对条件类型的设定:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* Copyright 2016 http://github.com/hs-web
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.hsweb.ezorm.core.param;

/**
* 查询条件类型,用于动态指定查询条件
*
* @author zhouhao
* @since 1.0
*/
public interface TermType {
/**
* ==
*
* @since 1.0
*/
String eq = "eq";
/**
* !=
*
* @since 1.0
*/
String not = "not";
/**
* like
*
* @since 1.0
*/
String like = "like";
/**
* not like
*
* @since 1.0
*/
String nlike = "nlike";
/**
* >
*
* @since 1.0
*/
String gt = "gt";
/**
* <
*
* @since 1.0
*/
String lt = "lt";
/**
* >=
*
* @since 1.0
*/
String gte = "gte";
/**
* <=
*
* @since 1.0
*/
String lte = "lte";
/**
* in
*
* @since 1.0
*/
String in = "in";
/**
* notin
*
* @since 1.0
*/
String nin = "nin";
/**
* =''
*
* @since 1.0
*/
String empty = "empty";
/**
* !=''
*
* @since 1.0
*/
String nempty = "nempty";
/**
* is null
*
* @since 1.0
*/
String isnull = "isnull";
/**
* not null
*
* @since 1.0
*/
String notnull = "notnull";
/**
* between
*
* @since 1.0
*/
String btw = "btw";
/**
* not between
*
* @since 1.0
*/
String nbtw = "nbtw";

/**
* 此类型将直接执行sql.在类型是从客户端参数中获取的场景中,应该屏蔽此类型
*
* @see SqlTerm
* @since 1.0
* @deprecated 此属性已弃用,如果想直接拼接sql,请使用 {@link SqlTerm}
*/
@Deprecated
String func = "func";
}
其次对于条件的设定:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package org.hsweb.ezorm.core.param;

import java.util.LinkedList;
import java.util.List;

/**
* 执行条件
*/
public class Term implements Cloneable {

/**
* 字段
*/
private String column;

/**
* 值
*/
private Object value;

/**
* 链接类型
*/
private Type type = Type.and;

/**
* 条件类型
*/
private String termType = TermType.eq;

/**
* 嵌套的条件
*/
private List<Term> terms = new LinkedList<>();


public Term or(String term, Object value) {
return or(term, TermType.eq,value);
}

public Term and(String term, Object value) {
return and(term, TermType.eq,value);
}

public Term or(String term, String termType, Object value) {
Term queryTerm = new Term();
queryTerm.setTermType(termType);
queryTerm.setColumn(term);
queryTerm.setValue(value);
queryTerm.setType(Type.or);
terms.add(queryTerm);
return this;
}

public Term and(String term, String termType, Object value) {
Term queryTerm = new Term();
queryTerm.setTermType(termType);
queryTerm.setColumn(term);
queryTerm.setValue(value);
queryTerm.setType(Type.and);
terms.add(queryTerm);
return this;
}

public Term nest() {
return nest(null, null);
}

public Term orNest() {
return orNest(null, null);
}

public Term nest(String term, Object value) {
Term queryTerm = new Term();
queryTerm.setType(Type.and);
queryTerm.setColumn(term);
queryTerm.setValue(value);
terms.add(queryTerm);
return queryTerm;
}

public Term orNest(String term, Object value) {
Term queryTerm = new Term();
queryTerm.setType(Type.or);
queryTerm.setColumn(term);
queryTerm.setValue(value);
terms.add(queryTerm);
return queryTerm;
}

public String getColumn() {
return column;
}

public void setColumn(String column) {
if (column == null) return;
if (column.contains("$")) {
String tmp[] = column.split("[$]");
setTermType(tmp[1]);
column = tmp[0];
}
this.column = column;
}

public Object getValue() {
return value;
}

public void setValue(Object value) {
this.value = value;
}

public Type getType() {
return type;
}

public void setType(Type type) {
this.type = type;
}

public String getTermType() {
return termType.toLowerCase();
}

public void setTermType(String termType) {
this.termType = termType;
}

public List<Term> getTerms() {
return terms;
}

public void setTerms(List<Term> terms) {
this.terms = terms;
}

public Term addTerm(Term term) {
terms.add(term);
return this;
}

@Override
public Term clone() {
Term term = new Term();
term.setColumn(column);
term.setValue(value);
term.setTermType(termType);
term.setType(type);
terms.forEach(t -> term.addTerm(t.clone()));
return term;
}

public enum Type {
or, and;

public static Type fromString(String str) {
try {
return Type.valueOf(str.toLowerCase());
} catch (Exception e) {
return and;
}
}
}


}

将各种条件用po来表达出来并进行封装

最后对于SQL参数对象的设定:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package org.hsweb.ezorm.core.param;


import java.util.*;
import java.util.stream.Collectors;

/**
* SQL参数对象
*
* @author zhouhao
* @since 1.0
*/
public class Param implements Cloneable {

/**
* 条件
*/
protected List<Term> terms = new LinkedList<>();

/**
* 指定要处理的字段
*/
protected Set<String> includes = new LinkedHashSet<>();

/**
* 指定不处理的字段
*/
protected Set<String> excludes = new LinkedHashSet<>();

public <T extends Param> T or(String column, Object value) {
return or(column, TermType.eq, value);
}

public <T extends Param> T and(String column, Object value) {
return and(column, TermType.eq, value);
}

public <T extends Param> T or(String column, String termType, Object value) {
Term term = new Term();
term.setTermType(termType);
term.setColumn(column);
term.setValue(value);
term.setType(Term.Type.or);
terms.add(term);
return (T) this;
}

public <T extends Param> T and(String column, String termType, Object value) {
Term term = new Term();
term.setTermType(termType);
term.setColumn(column);
term.setValue(value);
term.setType(Term.Type.and);
terms.add(term);
return (T) this;
}


public Term nest() {
return nest(null, null);
}

public Term orNest() {
return orNest(null, null);
}

public Term nest(String termString, Object value) {
Term term = new Term();
term.setColumn(termString);
term.setValue(value);
term.setType(Term.Type.and);
terms.add(term);
return term;
}

public Term orNest(String termString, Object value) {
Term term = new Term();
term.setColumn(termString);
term.setValue(value);
term.setType(Term.Type.or);
terms.add(term);
return term;
}

public <T extends Param> T includes(String... fields) {
includes.addAll(Arrays.asList(fields));
return (T) this;
}

public <T extends Param> T excludes(String... fields) {
excludes.addAll(Arrays.asList(fields));
includes.removeAll(Arrays.asList(fields));
return (T) this;
}

public <T extends Param> T where(String key, Object value) {
and(key, value);
return (T) this;
}

public <T extends Param> T where(String key, String termType, Object value) {
and(key, termType, value);
return (T) this;
}

public Set<String> getIncludes() {
if (includes == null) includes = new LinkedHashSet<>();
return includes;
}

public Set<String> getExcludes() {
if (excludes == null) excludes = new LinkedHashSet<>();
return excludes;
}

public void setIncludes(Set<String> includes) {
this.includes = includes;
}

public void setExcludes(Set<String> excludes) {
this.excludes = excludes;
}

public List<Term> getTerms() {
return terms;
}

public void setTerms(List<Term> terms) {
this.terms = terms;
}

public <T extends Param> T addTerm(Term term) {
terms.add(term);
return (T) this;
}

@Override
public Param clone() {
Param param = new Param();
param.setExcludes(new LinkedHashSet<>(excludes));
param.setIncludes(new LinkedHashSet<>(includes));
List<Term> terms = this.terms.stream().map(term -> term.clone()).collect(Collectors.toList());
param.setTerms(terms);
return param;
}
}

这里通过LinkedList 来将条件都包装到一起 ,通过LinkedHashSet来包装要处理的字段

Param衍生出来的专门对查询(如分页)和更新参数的额外封装:

查询往往会涉及到排序,这里对排序先做下封装:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package org.hsweb.ezorm.core.param;

/**
* 排序
*
* @author zhouhao
* @since 1.0
*/
public class Sort extends Column {

private String order = "asc";

private transient QueryParam queryParam;

public String getOrder() {
return order;
}

public void setOrder(String order) {
this.order = order;
}

public Sort() {
}

public Sort(QueryParam queryParam, String name) {
this.queryParam = queryParam;
setName(name);
}

public QueryParam asc() {
this.order = "asc";
return queryParam;
}

public QueryParam desc() {
this.order = "desc";
return queryParam;
}

public Sort and(String field) {
return queryParam.orderBy(field);
}

@Override
public int hashCode() {
return String.valueOf(getName()).concat(order).hashCode();
}

@Override
public boolean equals(Object obj) {
return obj != null && this.hashCode() == obj.hashCode();
}

}
QueryParam: 排序字段同样LinkedList存储
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package org.hsweb.ezorm.core.param;

import java.io.Serializable;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
* Created by 浩 on 2016-01-16 0016.
*/
public class QueryParam extends Param implements Serializable, Cloneable {
private static final long serialVersionUID = 7941767360194797891L;

/**
* 是否进行分页,默认为true
*/
private boolean paging = true;

/**
* 第几页 从0开始
*/
private int pageIndex = 0;

/**
* 每页显示记录条数
*/
private int pageSize = 25;


/**
* 排序字段
*
* @since 1.0
*/
private List<Sort> sorts = new LinkedList<>();


private boolean forUpdate = false;

public QueryParam select(String... fields) {
return this.includes(fields);
}

public Sort orderBy(String column) {
Sort sort = new Sort(this, column);
sorts.add(sort);
return sort;
}

public <Q extends QueryParam> Q doPaging(int pageIndex) {
this.pageIndex = pageIndex;
this.paging = true;
return (Q) this;
}

public <Q extends QueryParam> Q doPaging(int pageIndex, int pageSize) {
this.pageIndex = pageIndex;
this.pageSize = pageSize;
this.paging = true;
return (Q) this;
}

public <Q extends QueryParam> Q rePaging(int total) {
paging = true;
// 当前页没有数据后跳转到最后一页
if (this.getPageIndex() != 0 && (pageIndex * pageSize) >= total) {
int tmp = total / this.getPageSize();
pageIndex = total % this.getPageSize() == 0 ? tmp - 1 : tmp;
}
return (Q) this;
}

public boolean isPaging() {
return paging;
}

public void setPaging(boolean paging) {
this.paging = paging;
}

public int getPageIndex() {
return pageIndex;
}

public void setPageIndex(int pageIndex) {
this.pageIndex = pageIndex;
}

public int getPageSize() {
return pageSize;
}

public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}

public List<Sort> getSorts() {
return sorts;
}

public void setSorts(List<Sort> sorts) {
this.sorts = sorts;
}

public void setForUpdate(boolean forUpdate) {
this.forUpdate = forUpdate;
}

public boolean isForUpdate() {
return forUpdate;
}

@Override
public QueryParam clone() {
QueryParam sqlParam = new QueryParam();
sqlParam.setExcludes(new LinkedHashSet<>(excludes));
sqlParam.setIncludes(new LinkedHashSet<>(includes));
List<Term> terms = this.terms.stream().map(Term::clone).collect(Collectors.toList());
sqlParam.setTerms(terms);
sqlParam.setPageIndex(pageIndex);
sqlParam.setPageSize(pageSize);
sqlParam.setPaging(paging);
sqlParam.setSorts(sorts);
sqlParam.setForUpdate(forUpdate);
return sqlParam;
}
}
UpdateParam:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package org.hsweb.ezorm.core.param;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Collectors;

/**
* Created by zhouhao on 16-4-19.
*/
public class UpdateParam<T> extends Param {
private T data;

public UpdateParam() {
}

public UpdateParam(T data) {
this.data = data;
}

public <C extends UpdateParam<T>> C set(T data) {
this.data = data;
return (C) this;
}

public T getData() {
return data;
}

public void setData(T data) {
this.data = data;
}

@Override
public UpdateParam clone() {
UpdateParam<T> param = new UpdateParam<>();
param.setData(data);
param.setExcludes(new LinkedHashSet<>(excludes));
param.setIncludes(new LinkedHashSet<>(includes));
List<Term> terms = this.terms.stream().map(Term::clone).collect(Collectors.toList());
param.setTerms(terms);
return param;
}
}
对更新数据map类型包装的数据做扩展:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package org.hsweb.ezorm.core.param;

import java.util.HashMap;
import java.util.Map;

/**
* Created by zhouhao on 16-4-21.
*/
public class UpdateMapParam extends UpdateParam<Map<String, Object>> {
public UpdateMapParam() {
this(new HashMap<>());
}

public UpdateMapParam(Map<String, Object> data) {
setData(data);
}

public UpdateMapParam set(String key, Object value) {
this.getData().put(key, value);
return this;
}
}

表插入数据的封装

InsertParam:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package org.hsweb.ezorm.core.param;

public class InsertParam<T> {
private T data;

public InsertParam() {
}

public InsertParam(T data) {
this.data = data;
}

public InsertParam<T> value(T data) {
this.data = data;
return this;
}

public T getData() {
return data;
}

public void setData(T data) {
this.data = data;
}

public static <T> InsertParam<T> build(T data) {
return new InsertParam<>(data);
}
}

和更新针对map数据类型衍生一样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.hsweb.ezorm.core.param;

import java.util.HashMap;
import java.util.Map;

public class InsertParamMapParam extends InsertParam<Map<String, Object>> {

@Override
public Map<String, Object> getData() {
if (super.getData() == null) setData(new HashMap<>());
return super.getData();
}

public InsertParamMapParam value(String property, Object value) {
getData().put(property, value);
return this;
}

public InsertParamMapParam values(Map<String, Object> values) {
getData().putAll(values);
return this;
}
}

二,反映到表元素的元数据类MetaData

PO转表元素数据

OptionConverter:选项映射器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package org.hsweb.ezorm.core;

/**
* 选项映射器,当一个字段持有映射器时.
* <ul>
* <li>
* 在查询时,会追加一个名为{@link OptionConverter#getFieldName()}的字段为{@link OptionConverter#converterValue(Object)} 的值
* </li>
* <li>
* 在修改或者插入时,验证器会首先通过 {@link OptionConverter#converterData(Object)}来获取一个结果.
* 如果返回null.则调用{@link OptionConverter#converterValue(Object)} ,并将值放入数据库.
* 如果继续返回null,则会抛出验证器异常,提示值不再选项范围中
* </li>
* </ul>
* Created by zhouhao on 16-6-4.
*/
public interface OptionConverter {

/**
* 获取所有选项
*
* @return 选项
*/
Object getOptions();

/**
* 获取转换后的字段名称
*
* @return 转换后的字段名称
*/
String getFieldName();

/**
* 将提交的数据,转换为目标数据
*
* @param value 提交的数据
* @return 转换结果
*/
Object converterData(Object value);

/**
* 将数据库的数据,转换为目标数据
*
* @param data 数据库数据
* @return 转换结果
*/
Object converterValue(Object data);

}
PropertyWrapper:属性包装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package org.hsweb.ezorm.core;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;

public interface PropertyWrapper extends Serializable {
<T> T getValue();

String toString();

int toInt();

double toDouble();

boolean isTrue();

Date toDate();

Date toDate(String format);

Map<String, Object> toMap();

List<Map> toList();

<T> T toBean(Class<T> type);

<T> List<T> toBeanList(Class<T> type);

boolean isNullOrEmpty();

boolean valueTypeOf(Class<?> type);
}

PropertyWrapper的简单实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package org.hsweb.ezorm.core;

import com.alibaba.fastjson.JSON;
import org.hsweb.commons.ClassUtils;
import org.hsweb.commons.DateTimeUtils;
import org.hsweb.commons.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* Created by zhouhao on 16-6-4.
*/
public class SimplePropertyWrapper implements PropertyWrapper {

private Object value;

public SimplePropertyWrapper(Object value) {
this.value = value;
}

@Override
public <T> T getValue() {
return (T) value;
}

@Override
public int toInt() {
return StringUtils.toInt(value);
}

@Override
public double toDouble() {
return StringUtils.toDouble(value);
}

@Override
public boolean isTrue() {
return StringUtils.isTrue(value);
}

@Override
public Date toDate() {
if (value instanceof Date) return ((Date) value);
return DateTimeUtils.formatUnknownString2Date(toString());
}

@Override
public Date toDate(String format) {
if (value instanceof Date) return ((Date) value);
return DateTimeUtils.formatDateString(toString(), format);
}

@Override
public <T> T toBean(Class<T> type) {
if (valueTypeOf(type)) return ((T) getValue());
return JSON.parseObject(toString(), type);
}

@Override
public List<Map> toList() {
return toBeanList(Map.class);
}

@Override
public Map<String, Object> toMap() {
return toBean(Map.class);
}

@Override
public <T> List<T> toBeanList(Class<T> type) {
if (getValue() instanceof List) return ((List) getValue());
return JSON.parseArray(toString(), type);
}

@Override
public boolean isNullOrEmpty() {
return StringUtils.isNullOrEmpty(value);
}

@Override
public boolean valueTypeOf(Class<?> type) {
if (value == null) return false;
return ClassUtils.instanceOf(value.getClass(), type);
}

@Override
public String toString() {
return String.valueOf(value);
}

}
ValueConverter:数据转换
1
2
3
4
5
6
7
package org.hsweb.ezorm.core;

public interface ValueConverter {
Object getData(Object value);

Object getValue(Object data);
}

由其所衍生的类:

这里只看其中一两个即可:

ClobValueConverter:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package org.hsweb.ezorm.rdb.meta.converter;


import org.hsweb.ezorm.core.ValueConverter;

import java.io.Reader;
import java.sql.Clob;

public class ClobValueConverter implements ValueConverter {
@Override
public Object getData(Object value) {
return value;
}

@Override
public Object getValue(Object data) {
if (data instanceof Clob) {
Clob clobData = ((Clob) data);
try (Reader reader = clobData.getCharacterStream()) {
char[] chars = new char[(int) clobData.length()];
reader.read(chars);
data = new String(chars);
} catch (Exception ignored) {
}
}
return data;
}
}
BooleanValueConverter:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package org.hsweb.ezorm.rdb.meta.converter;

import org.hsweb.ezorm.core.ValueConverter;

public class BooleanValueConverter implements ValueConverter {

@Override
public Object getData(Object value) {
return value;
}

@Override
public Object getValue(Object data) {
if (null == data) return false;
if (data instanceof Boolean) return data;
return "1".equals(String.valueOf(data)) || "true".equals(String.valueOf(data));
}
}
对象包装ObjectWrapper:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
* Copyright 2016 http://github.com/hs-web
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.hsweb.ezorm.core;


import java.util.List;

/**
* 对象包装器,在执行查询时,通过包装器对查询结果进行初始化
*
* @author zhouhao
* @since 1.0
*/
public interface ObjectWrapper<T> {
/**
* 执行初始化,在sql执行后,包装结果前,将调用此方法,传入查询的列
*
* @param columns 列集合
*/
default void setUp(List<String> columns) {
}

<C extends T> Class<C> getType();

/**
* 创建对象实例
*
* @return 对象实例
*/
T newInstance();

/**
* 向实例中填充一个属性值
*
* @param instance 实例对象
* @param index 当前实例的索引
* @param attr 属性名称
* @param value 属性值
*/
void wrapper(T instance, int index, String attr, Object value);

/**
* 当一个实例被填充完成后调用,已进行其他操作
*
* @param instance 实例对象
*/
void done(T instance);


}

其衍生的类:

触发:Trigger:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package org.hsweb.ezorm.core;


import java.util.Map;

public interface Trigger {

void execute(Map<String, Object> context);

String select_before = "select.before";
String select_wrapper_each = "select.wrapper.each";
String select_wrapper_done = "select.wrapper.done";
String select_done = "select.done";
String insert_before = "insert.before";
String insert_done = "insert.done";
String update_before = "update.before";
String update_done = "update.done";
String delete_before = "delete.before";
String delete_done = "delete.done";
}
定义TableMetaData
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package org.hsweb.ezorm.core.meta;

import org.hsweb.ezorm.core.ObjectWrapper;
import org.hsweb.ezorm.core.PropertyWrapper;
import org.hsweb.ezorm.core.Trigger;

import java.io.Serializable;
import java.util.Map;
import java.util.Set;

/**
* @author zhouhao
*/
public interface TableMetaData extends Serializable {
String getName();

String getComment();

String getAlias();

<T extends DatabaseMetaData> T getDatabaseMetaData();

<T extends ColumnMetaData> Set<T> getColumns();

<T extends ColumnMetaData> T getColumn(String name);

<T extends ColumnMetaData> T findColumn(String name);

<T> ObjectWrapper<T> getObjectWrapper();

PropertyWrapper getProperty(String property);

PropertyWrapper getProperty(String property, Object defaultValue);

PropertyWrapper setProperty(String property, Object value);

void on(String name, Trigger trigger);

void on(String name, Map<String, Object> triggerContext);

boolean triggerIsSupport(String name);
}

里面包含有表名字,注释,别名,然后就是表所属数据库的元数据信息,表包含列的元数据信息,以及对象的包装,属性的包装,见上面对象包装,属性的包装,以及通过on()方法对Trigger使用

定义DatabaseMetaData
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package org.hsweb.ezorm.core.meta;

import org.hsweb.ezorm.core.ObjectWrapperFactory;
import org.hsweb.ezorm.core.ValidatorFactory;

public interface DatabaseMetaData {

ObjectWrapperFactory getObjectWrapperFactory();

ValidatorFactory getValidatorFactory();

<T extends TableMetaData> T getTableMetaData(String name);

}

个人认为,其实这里表达的就是衔接的意思,ObjectWrapperTableMetaData信息的对应(等以后有新的理解了再来修改的)

ValidatorFactory

1
2
3
4
5
6
7
package org.hsweb.ezorm.core;

import org.hsweb.ezorm.core.meta.TableMetaData;

public interface ValidatorFactory {
Validator createValidator(TableMetaData tableMetaData);//源码里暂时未使用到该接口方法定义
}

Validator其实是对INSERT, UPDATE操作和相应数据进行下验证

1
2
3
4
5
6
7
8
9
10
package org.hsweb.ezorm.core;


public interface Validator {
boolean validate(Object data, Operation operation);

enum Operation {
INSERT, UPDATE
}
}
定义ColumnMetaData
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package org.hsweb.ezorm.core.meta;


import org.hsweb.ezorm.core.OptionConverter;
import org.hsweb.ezorm.core.PropertyWrapper;
import org.hsweb.ezorm.core.ValueConverter;

import java.io.Serializable;
import java.util.Set;

public interface ColumnMetaData extends Serializable, Cloneable {
String getName();

String getAlias();

String getComment();

Class getJavaType();

<T extends TableMetaData> T getTableMetaData();

ValueConverter getValueConverter();

OptionConverter getOptionConverter();

Set<String> getValidator();

PropertyWrapper getProperty(String property);

PropertyWrapper getProperty(String property, Object defaultValue);

PropertyWrapper setProperty(String property, Object value);

<T extends ColumnMetaData> T clone();
}

里面包含有表名字,注释,别名,然后就是列所属表的元数据信息,表包含列的元数据信息,以及值的转换,选项的转换,属性的包装,见上面数据转换,属性的包装小节,以及通过clone()方法返回相应的ColumnMetaData的实现

TableMetaDataStorage定义

以上三个MetaData元素定义完之后,通过TableMetaDataStorage来对表元数据做存储方面的一些操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package org.hsweb.ezorm.core.meta.storage;

import org.hsweb.ezorm.core.meta.TableMetaData;

import java.util.Set;

public interface TableMetaDataStorage {

<T extends TableMetaData> Set<T> getAllTableMetaData();

<T extends TableMetaData> T getTableMetaData(String nameOrAlias);

<T extends TableMetaData> T removeTableMeta(String nameOrAlias);

<T extends TableMetaData> T putTableMetaData(T table);

void clear();

}

因为本就是key-value形式保存的,那么很自然就衍生成map类型的实现类: 都是一些map方面的操作,就不多说了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package org.hsweb.ezorm.core.meta.storage;

import org.hsweb.ezorm.core.meta.TableMetaData;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

public class MapTableMetaDataStorage implements TableMetaDataStorage {
private final Map<String, TableMetaData> nameTableMetaDataStorage = new HashMap<>();
private final Map<String, TableMetaData> aliasTableMetaDataStorage = new HashMap<>();

@Override
public <T extends TableMetaData> Set<T> getAllTableMetaData() {
Set<T> all = new LinkedHashSet<>();
all.addAll((Set) nameTableMetaDataStorage.values());
return all;
}

@Override
public <T extends TableMetaData> T getTableMetaData(String nameOrAlias) {
T old = (T) nameTableMetaDataStorage.get(nameOrAlias);
if (old == null) old = (T) aliasTableMetaDataStorage.get(nameOrAlias);
return old;
}

@Override
public <T extends TableMetaData> T removeTableMeta(String nameOrAlias) {
T old = (T) nameTableMetaDataStorage.remove(nameOrAlias);
T old2 = (T) aliasTableMetaDataStorage.remove(nameOrAlias);
return old != null ? old : old2;
}

@Override
public <T extends TableMetaData> T putTableMetaData(T table) {
nameTableMetaDataStorage.put(table.getName(), table);
if (!table.getName().equals(table.getAlias())) {
nameTableMetaDataStorage.put(table.getAlias(), table);
}
return table;
}

@Override
public void clear() {
nameTableMetaDataStorage.clear();
aliasTableMetaDataStorage.clear();
}
}
对上面定义的三个元数据类型接口的抽象实现:
对于DatabaseMetaData的初步通用实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package org.hsweb.ezorm.core.meta;

import org.hsweb.ezorm.core.ObjectWrapperFactory;
import org.hsweb.ezorm.core.ValidatorFactory;
import org.hsweb.ezorm.core.meta.storage.MapTableMetaDataStorage;
import org.hsweb.ezorm.core.meta.storage.TableMetaDataStorage;

public abstract class AbstractDatabaseMetaData implements DatabaseMetaData {
protected ObjectWrapperFactory objectWrapperFactory;
protected ValidatorFactory validatorFactory;
protected TableMetaDataStorage tableMetaDataStorage=new MapTableMetaDataStorage();

@Override
public <T extends TableMetaData> T getTableMetaData(String name) {
return tableMetaDataStorage.getTableMetaData(name);
}

@Override
public ObjectWrapperFactory getObjectWrapperFactory() {
return objectWrapperFactory;
}

@Override
public ValidatorFactory getValidatorFactory() {
return validatorFactory;
}

public void setObjectWrapperFactory(ObjectWrapperFactory objectWrapperFactory) {
this.objectWrapperFactory = objectWrapperFactory;
}

public void setValidatorFactory(ValidatorFactory validatorFactory) {
this.validatorFactory = validatorFactory;
}

public void setTableMetaDataStorage(TableMetaDataStorage tableMetaDataStorage) {
this.tableMetaDataStorage = tableMetaDataStorage;
}
}
对于TableMetaData的初步通用实现:

properties triggerBase都是用map来进行相应包装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package org.hsweb.ezorm.core.meta;

import org.hsweb.ezorm.core.*;

import java.util.*;

public abstract class AbstractTableMetaData<C extends AbstractColumnMetaData> implements TableMetaData {
//表名称
protected String name = null;
//表别名,如果指定了别名,查询结果将使用别名进行封装
protected String alias = null;
//备注
protected String comment = null;
//表字段
protected Map<String, C> columnMetaDataMap = new LinkedHashMap<>();
protected Map<String, C> aliasColumnMetaDataMap = new LinkedHashMap<>();
protected Validator validator = null;
protected ObjectWrapper objectWrapper = null;
protected Map<String, Object> properties = new HashMap<>();
protected Map<String, Trigger> triggerBase = new HashMap<>();

@Override
public <T> ObjectWrapper<T> getObjectWrapper() {
return objectWrapper;
}

public void setObjectWrapper(ObjectWrapper objectWrapper) {
this.objectWrapper = objectWrapper;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAlias() {
if (alias == null) alias = name;
return alias;
}

public <T extends AbstractTableMetaData<C>> T addColumn(C columnMetaData) {
columnMetaData.setTableMetaData(this);
columnMetaDataMap.put(columnMetaData.getName(), columnMetaData);
if (!columnMetaData.getName().equals(columnMetaData.getAlias()))
aliasColumnMetaDataMap.put(columnMetaData.getAlias(), columnMetaData);
return (T) this;
}

public void setAlias(String alias) {
this.alias = alias;
}

public void on(String triggerName, Trigger trigger) {
triggerBase.put(triggerName, trigger);
}

public void on(String triggerName, Map<String, Object> context) {
if (triggerIsSupport(triggerName)) {
Trigger trigger = triggerBase.get(triggerName);
trigger.execute(context);
}
}

@Override
public Set<C> getColumns() {
return new LinkedHashSet<>(columnMetaDataMap.values());
}

public void removeColumn(String name) {
columnMetaDataMap.remove(name);
aliasColumnMetaDataMap.remove(name);
}

public boolean triggerIsSupport(String name) {
return triggerBase.containsKey(name);
}

public PropertyWrapper getProperty(String name) {
return new SimplePropertyWrapper(properties.get(name));
}

public PropertyWrapper getProperty(String name, Object defaultValue) {
return new SimplePropertyWrapper(properties.getOrDefault(name, defaultValue));
}

public PropertyWrapper removeProperty(String name) {
return new SimplePropertyWrapper(properties.remove(name));
}

public PropertyWrapper setProperty(String property, Object value) {
return new SimplePropertyWrapper(properties.put(property, value));
}


public abstract C findColumn(String name);

public String getComment() {
return comment;
}

@Override
public C getColumn(String name) {
C metaData = columnMetaDataMap.get(name);
if (metaData == null) metaData = aliasColumnMetaDataMap.get(name);
return metaData;
}

public void setComment(String comment) {
this.comment = comment;
}

public Map<String, Object> getProperties() {
return properties;
}

public void setProperties(Map<String, Object> properties) {
this.properties = properties;
}

public Validator getValidator() {
return validator;
}

public void setValidator(Validator validator) {
this.validator = validator;
}

@Override
public String toString() {
return name + " [" + alias + "]" + "(" + comment + ")";
}
}
对于ColumnMetaData的初步通用实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package org.hsweb.ezorm.core.meta;

import org.hsweb.ezorm.core.OptionConverter;
import org.hsweb.ezorm.core.PropertyWrapper;
import org.hsweb.ezorm.core.SimplePropertyWrapper;
import org.hsweb.ezorm.core.ValueConverter;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public abstract class AbstractColumnMetaData implements ColumnMetaData {
protected String name;
protected String alias;
protected String comment;
protected Class javaType;
protected TableMetaData tableMetaData;
protected OptionConverter optionConverter;
protected ValueConverter valueConverter;
protected Set<String> validator;
protected Map<String, Object> properties = new HashMap<>();

@Override
public String getName() {
return name;
}

@Override
public String getAlias() {
if (alias == null) alias = name;
return alias;
}

@Override
public String getComment() {
if (comment == null) comment = "";
return comment;
}

@Override
public Class getJavaType() {
return javaType;
}

@Override
public Set<String> getValidator() {
return validator;
}

@Override
public <T extends TableMetaData> T getTableMetaData() {
return (T) tableMetaData;
}

@Override
public ValueConverter getValueConverter() {
return valueConverter;
}

@Override
public OptionConverter getOptionConverter() {
return optionConverter;
}

@Override
public PropertyWrapper getProperty(String property) {
return new SimplePropertyWrapper(properties.get(property));
}

@Override
public PropertyWrapper getProperty(String property, Object defaultValue) {
Object value = properties.get(property);
return new SimplePropertyWrapper(value == null ? defaultValue : value);
}

@Override
public PropertyWrapper setProperty(String property, Object value) {
return new SimplePropertyWrapper(properties.put(property, value));
}

public void setName(String name) {
this.name = name;
}

public void setAlias(String alias) {
this.alias = alias;
}

public void setComment(String comment) {
this.comment = comment;
}

public void setJavaType(Class javaType) {
this.javaType = javaType;
}

public void setTableMetaData(TableMetaData tableMetaData) {
this.tableMetaData = tableMetaData;
}

public void setOptionConverter(OptionConverter optionConverter) {
this.optionConverter = optionConverter;
}

public void setValueConverter(ValueConverter valueConverter) {
this.valueConverter = valueConverter;
}

public void setValidator(Set<String> validator) {
this.validator = validator;
}

public Map<String, Object> getProperties() {
return properties;
}

public void setProperties(Map<String, Object> properties) {
this.properties = properties;
}

@Override
public abstract AbstractColumnMetaData clone();
}

因篇幅有点长,增删改查的相关操作在下一篇中说

您的支持将鼓励我继续创作!